﻿#region - 版 本 注 释 -
/*----------------------------------------------------------------
 * 版权所有 (c) 2024   保留所有权利。
 * CLR版本：4.0.30319.42000
 * 机器名称：DESKTOP-GLJ2Q8J
 * 公司名称：
 * 命名空间：AutoCAD.EntityTool
 * 唯一标识：b893f674-d9d1-4fd6-88a5-6b43f5b1d8e0
 * 文件名：BlockTools
 * 当前用户域：DESKTOP-GLJ2Q8J
 * 
 * 创建者：Guo-79991
 * 电子邮箱：799919859@qq.com
 * 创建时间：2024/7/15 12:05:36
 * 版本：V1.0.0
 *
 * 功能描述(Description):
 * 参考文档(Reference):
 * 数据表(Tables):
 * 作者(Author):Guo
 *
 * ----------------------------------------------------------------
 * 修改人：
 * 时间：
 * 修改说明：
 *
 * 版本：V1.0.1
 *----------------------------------------------------------------*/
#endregion - 版 本 注 释 -


namespace AutoCAD.EntityTools.Jig
{
    /// <summary>
    /// 圆Jig
    /// </summary>
    public class CircleJig : EntityJig
    {
        private Point3d _centerPoint;
        private Point3d _radiusPoint;
        private double _radius;
        private string _prompt;
        private string[] _keywords;
        private bool _isDiameterMode;

        /// <summary>
        /// 圆Jig构造函数
        /// </summary>
        public CircleJig(Point3d centerPoint, string prompt, string[] keywords = null, bool isDiameterMode = false)
            : base(new Circle())
        {
            _centerPoint = centerPoint;
            _prompt = prompt;
            _keywords = keywords;
            _isDiameterMode = isDiameterMode;

            // 初始化圆
            ((Circle)Entity).Center = _centerPoint;
            ((Circle)Entity).Radius = 0.1; // 设置一个小的初始半径避免退化几何
            ((Circle)Entity).Normal = Vector3d.ZAxis; // 确保法向量正确
        }

        protected override SamplerStatus Sampler(JigPrompts prompts)
        {
            var jigOptions = new JigPromptPointOptions(_prompt)
            {
                UserInputControls = UserInputControls.Accept3dCoordinates |
                                   UserInputControls.NoNegativeResponseAccepted,
                AppendKeywordsToMessage = false,
                BasePoint = _centerPoint,
                UseBasePoint = true
            };

            // 添加关键字
            if (_keywords != null && _keywords.Length > 0)
            {
                foreach (var keyword in _keywords)
                {
                    jigOptions.Keywords.Add(keyword);
                }
            }

            // 添加空格作为确认关键字
            jigOptions.Keywords.Add(" ");
            jigOptions.Keywords.Add("Cancel");

            var promptResult = prompts.AcquirePoint(jigOptions);

            if (promptResult.Status == PromptStatus.Cancel ||
                promptResult.Status == PromptStatus.Error)
                return SamplerStatus.Cancel;

            if (promptResult.Status == PromptStatus.Keyword)
            {
                return SamplerStatus.OK;
            }

            // 检查点是否有效
            if (promptResult.Value.DistanceTo(_centerPoint) < Tolerance.Global.EqualPoint)
            {
                // 如果距离太小，设置一个最小半径
                _radius = 0.1;
                return SamplerStatus.NoChange;
            }

            if (_radiusPoint.DistanceTo(promptResult.Value) < Tolerance.Global.EqualPoint)
                return SamplerStatus.NoChange;

            _radiusPoint = promptResult.Value;
            _radius = _centerPoint.DistanceTo(_radiusPoint);

            // 确保半径不小于最小值
            if (_radius < 0.1)
                _radius = 0.1;

            return SamplerStatus.OK;
        }

        protected override bool Update()
        {
            try
            {
                var circle = (Circle)Entity;
                circle.Center = _centerPoint;
                circle.Radius = _radius;
                circle.Normal = Vector3d.ZAxis; // 确保法向量正确

                return true;
            }
            catch
            {
                // 如果更新失败，设置一个安全的半径值
                ((Circle)Entity).Radius = 1.0;
                return true;
            }
        }

        /// <summary>
        /// 获取创建的圆实体
        /// </summary>
        public Circle GetCircle() => (Circle)Entity;

        /// <summary>
        /// 获取圆的半径
        /// </summary>
        public double GetRadius() => _radius;

        /// <summary>
        /// 获取圆的直径
        /// </summary>
        public double GetDiameter() => _radius * 2;

        /// <summary>
        /// 设置直径模式
        /// </summary>
        public void SetDiameterMode(bool isDiameterMode) => _isDiameterMode = isDiameterMode;
    }

    public static class CircleCreationExtensions
    {
        private const double MinimumRadius = 0.1;

        /// <summary>
        /// 创建圆（自动添加到模型空间）
        /// </summary>
        public static ObjectId CreateCircle(this Document document, short colorIndex = 1)
        {
            return CreateCircleInternal(document, null, null, colorIndex);
        }

        /// <summary>
        /// 创建圆（指定事务和块表记录）
        /// </summary>
        public static ObjectId CreateCircle(this Document document, Transaction transaction,
            BlockTableRecord blockTableRecord, short colorIndex = 1, string message = "指定圆心点")
        {
            if (transaction == null) throw new ArgumentNullException(nameof(transaction));
            if (blockTableRecord == null) throw new ArgumentNullException(nameof(blockTableRecord));

            return CreateCircleInternal(document, transaction, blockTableRecord, colorIndex, message);
        }

        private static ObjectId CreateCircleInternal(Document document,
            Transaction transaction, BlockTableRecord blockTableRecord,
            short colorIndex, string message = "指定圆心点")
        {
            var editor = document.Editor;
            var database = document.Database;

            try
            {
                // 获取圆心点
                var centerPointResult = editor.GetPoint(message);
                if (centerPointResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                var centerPoint = centerPointResult.Value;

                // 创建并运行Jig
                var circleJig = new CircleJig(centerPoint, "\n指定半径或 [直径(D)/取消(Cancel)]:", new[] { "D", "Cancel" });
                var dragResult = editor.Drag(circleJig);

                Circle circle = null;

                switch (dragResult.Status)
                {
                    case PromptStatus.OK:
                        circle = circleJig.GetCircle();
                        break;

                    case PromptStatus.Keyword:
                        switch (dragResult.StringResult)
                        {
                            case "D":
                                circle = CreateCircleByDiameter(editor, centerPoint);
                                break;
                            case "Cancel":
                                return ObjectId.Null;
                            case " ":
                                return ObjectId.Null;
                        }
                        break;

                    case PromptStatus.Cancel:
                        return ObjectId.Null;

                    default:
                        return ObjectId.Null;
                }

                if (circle == null || circle.Radius < MinimumRadius)
                {
                    editor.WriteMessage("\n创建失败: 半径太小或无效");
                    return ObjectId.Null;
                }

                // 验证几何有效性
                if (!IsValidCircle(circle))
                {
                    editor.WriteMessage("\n创建失败: 无效的几何数据");
                    return ObjectId.Null;
                }

                circle.ColorIndex = colorIndex;

                ObjectId circleId;
                if (transaction != null && blockTableRecord != null)
                {
                    circleId = circle.AddToDatabase(transaction, blockTableRecord);
                }
                else
                {
                    circleId = database.AddEntityToModelSpace(circle);
                }

                editor.WriteMessage($"\n创建成功! 半径: {circle.Radius:F2}, 直径: {circle.Radius * 2:F2}");
                return circleId;
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n创建圆时发生错误: {ex.Message}");
                return ObjectId.Null;
            }
        }

        /// <summary>
        /// 检查圆是否有效
        /// </summary>
        private static bool IsValidCircle(Circle circle)
        {
            try
            {
                // 检查半径是否有效
                if (circle.Radius < MinimumRadius || double.IsNaN(circle.Radius) || double.IsInfinity(circle.Radius))
                    return false;

                // 检查中心点是否有效
                if (double.IsNaN(circle.Center.X) || double.IsNaN(circle.Center.Y) || double.IsNaN(circle.Center.Z))
                    return false;

                // 检查法向量是否有效
                if (circle.Normal.IsZeroLength() || double.IsNaN(circle.Normal.X))
                    return false;

                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 通过直径方式创建圆
        /// </summary>
        private static Circle CreateCircleByDiameter(Editor editor, Point3d centerPoint)
        {
            try
            {
                // 获取第一个直径端点
                var firstPointResult = editor.GetPoint("\n指定直径第一个端点:");
                if (firstPointResult.Status != PromptStatus.OK)
                    return null;

                var firstPoint = firstPointResult.Value;

                // 检查点是否有效
                if (firstPoint.DistanceTo(centerPoint) < Tolerance.Global.EqualPoint)
                {
                    editor.WriteMessage("\n错误: 端点不能与圆心重合");
                    return null;
                }

                // 使用Jig获取第二个直径端点
                var prompt = "\n指定直径第二个端点:";
                var diameterJig = new CircleJig(centerPoint, prompt, null, true);

                // 设置初始半径
                var initialVector = firstPoint - centerPoint;
                if (initialVector.Length > MinimumRadius)
                {
                    diameterJig.GetCircle().Radius = initialVector.Length;
                }

                var dragResult = editor.Drag(diameterJig);

                if (dragResult.Status != PromptStatus.OK)
                    return null;

                var secondPoint = diameterJig.GetCircle().Center +
                                (diameterJig.GetCircle().Center - centerPoint).GetNormal() * diameterJig.GetRadius();

                // 计算直径和半径
                double diameter = firstPoint.DistanceTo(secondPoint);

                // 确保直径有效
                if (diameter < MinimumRadius * 2)
                {
                    editor.WriteMessage("\n错误: 直径太小");
                    return null;
                }

                double radius = diameter / 2;

                var circle = new Circle(centerPoint, Vector3d.ZAxis, radius);

                if (!IsValidCircle(circle))
                {
                    editor.WriteMessage("\n错误: 创建了无效的圆");
                    return null;
                }

                return circle;
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n直径方式创建圆时发生错误: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 简化版圆创建（避免复杂的Jig操作）
        /// </summary>
        public static ObjectId CreateSimpleCircle(this Document document, short colorIndex = 1)
        {
            var editor = document.Editor;
            var database = document.Database;

            try
            {
                // 获取圆心点
                var centerResult = editor.GetPoint("指定圆心点:");
                if (centerResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                var centerPoint = centerResult.Value;

                // 获取半径
                var radiusOptions = new PromptDistanceOptions("\n指定半径:")
                {
                    DefaultValue = 10.0,
                    UseBasePoint = true,
                    BasePoint = centerPoint
                };

                var radiusResult = editor.GetDistance(radiusOptions);
                if (radiusResult.Status != PromptStatus.OK)
                    return ObjectId.Null;

                double radius = radiusResult.Value;

                // 确保半径有效
                if (radius < MinimumRadius)
                {
                    editor.WriteMessage($"\n警告: 半径太小，已设置为最小值 {MinimumRadius}");
                    radius = MinimumRadius;
                }

                // 创建圆
                var circle = new Circle(centerPoint, Vector3d.ZAxis, radius)
                {
                    ColorIndex = colorIndex
                };

                return database.AddEntityToModelSpace(circle);
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n创建圆时发生错误: {ex.Message}");
                return ObjectId.Null;
            }
        }

        /// <summary>
        /// 批量创建多个圆
        /// </summary>
        public static List<ObjectId> CreateMultipleCircles(this Document document, short colorIndex = 1, int maxCount = 10)
        {
            var editor = document.Editor;
            var database = document.Database;
            var circleIds = new List<ObjectId>();

            try
            {
                editor.WriteMessage($"\n开始创建圆，最多创建 {maxCount} 个。按ESC取消，按空格结束。");

                for (int i = 0; i < maxCount; i++)
                {
                    editor.WriteMessage($"\n创建第 {i + 1} 个圆:");

                    // 使用简化版避免Jig问题
                    var circleId = document.CreateSimpleCircle(colorIndex);
                    if (circleId.IsNull)
                        break;

                    circleIds.Add(circleId);

                    // 询问是否继续
                    if (i < maxCount - 1)
                    {
                        var keywordOptions = new PromptKeywordOptions("\n继续创建下一个圆？[是(Y)/否(N)]:")
                        {
                            AllowNone = true,
                            AppendKeywordsToMessage = true
                        };
                        keywordOptions.Keywords.Add("Y");
                        keywordOptions.Keywords.Add("N");
                        keywordOptions.Keywords.Default = "Y";

                        var result = editor.GetKeywords(keywordOptions);
                        if (result.Status != PromptStatus.OK || result.StringResult == "N")
                            break;
                    }
                }

                editor.WriteMessage($"\n成功创建 {circleIds.Count} 个圆");
                return circleIds;
            }
            catch (Exception ex)
            {
                editor.WriteMessage($"\n创建圆时发生错误: {ex.Message}");
                // 清理已创建的圆
                foreach (var id in circleIds)
                {
                    try { id.EraseEntity(); } catch { }
                }
                return new List<ObjectId>();
            }
        }
    }
}